2021-05-15
TypeScript 공식 문서가 갱신 되었다. 조건부 type등 다양한 자료가 생겼으니 찾아보는 것도 좋을 듯.
2020-08-26 정리되지 않은 노트
TypeScript로 타이핑을 잘하면 런타임 전에 미리 알 수 있는 오류도 있다.
타입 스크립트는 둘다.
구현자가 만든 함수를 사용자가 형태를 보고 사용 한다. 타입 = 변수가 할 수 있는 일을 정의
사용자는 함수의 기능을 판단할 때
noImplicitAny 옵션을 키면 명시적 any를 사용 (인자를 strict하게) strictNullChecks 기본 null, undefined 를 제거 noImplicitReturn 리턴을 명시적으로, 제대로된 리턴이 없을 때 에러
function f5(a: number): number{
if (a > 0)
return a * 38;
// return ?
}
오브젝트 구조를 잡는 두가지 방법 Interface방식과 type 방식
interface PersonInterface {
}
type PersonType = {
name: string;
}
읽어보기: [[Structural vs Nominal Subtyping 그리고 TypeScript]]
type PersonID = string & { readonly brand: unique symbol}
이렇게 intersection 시킬 수 있음
function getPersonById(id: PersonID): PersonID {
return id as PersonID;
}
function getPersonById() {}
getPersonById(PersonID('id-aaaa'));
읽어보기: 자주 쓰는 타입
두개의 interface를 & 로 합침, extends A,B
type ID = number | string;
type Animal = Bird | Fish;
타입이 같거나 서브 타입인 경우 할당이 가능.
// 투플 선언법
let sub3: [number, number];
// 서브타입 할당
let sub6: SubDog = new SubDog();
let sup6: Animal = sub6
// sub1타입은 sup1타입의 서브 타입
let sub1: 1 = 1;
let sup1: number = sub1;
함수의 매개변수 타입만 같거나 슈퍼 타입인 경우, 할당이 가능
class Person {}
class Developer extends Person {
coding() {}
}
class StartupDeveloper extends Developer {
burning() {}
}
function tellme(f: (d: Developer) => Developer) {}
// Developer => Developer 에다가 Developer => Developer 를 할당하는 경우
tellme(function dToD(d: Developer): Developer {
return new Developer();
});
// Developer => Developer 에다가 Person => Developer 를 할당하는 경우
tellme(function pToD(d: Person): Developer {
return new Developer();
});
// Developer => Developer 에다가 StartupDeveloper => Developer 를 할당하는 경우
tellme(function sToD(d: StartupDeveloper): Developer {
return new Developer();
});
strictFunctionTypes 옵션을 켜면 이외의 경우에 에러
any대신에 unknown을 사용하면? 받는 건 마음대로 인데 함수를 일단 안된다고 보고 type 제한 조건을 if문으로 각각 처리. unknown을 쓰는 것이 안정성을 높인다.
let 과 const의 타입 추론
const는 literal type 딱 초기화된 값들만 들어감 let은 type을 가짐
Best Common Type
let j = [0,1,null]; // (number | null)
이런식으로 최대한 넓은 범위로
만약 더 strict하고 싶다면 as const를 붙여주는 것이지
부모 타입으로 만들고 싶으면 타입 명시를 하거나 부모가 배열 안에 같이 들어가면 부모로 추론이 된다.
let l = [new Rhino(), new Elephant(), new Snake()]; // (Rhino | Elephant | Snake)[]
const m = [new Rhino(), new Elephant(), new Snake()]; // (Rhino | Elephant | Snake)[]
const n = [new Animal(), new Rhino(), new Elephant(), new Snake()]; // Animal[]
const o: Animal[] = [new Rhino(), new Elephant(), new Snake()]; // Animal[]
Contextual Typing
// Parameter 'e' implicitly has an 'any' type.
const click = (e) => {
e; // any
};
document.addEventListener('click', click);
document.addEventListener('click', (e) => {
e; // MouseEvent
});
primitive 타입일 때
function getNumber(value: number | string): number {
value; // number | string
if (typeof value === 'number') {
value; // number
// 여기서 number를 처리했으므로 Type이 떨어져나간다.
return value;
}
value; // string
return -1;
}
Error 객체 구분에 많이 쓰임
class NegativeNumberError extends Error {}
function getNumber(value: number): number | NegativeNumberError { // 이런 식으로
if (value < 0) return new NegativeNumberError();
return value;
}
function main() {
const num = getNumber(-10);
if (num instanceof NegativeNumberError) {
return;
}
num; // number
}
프로퍼티가 있냐? 없냐? 로 조건
interface Admin {
id: string;
role: string:
}
interface User {
id: string;
email: string;
}
function redirect(user: Admin | User) {
if("role" in user) {
routeToAdminPage(user.role);
} else {
routeToHomePage(user.email);
}
}
프로퍼티가 같고 type이 다른 경우 클래스 내에 type: 'BOAT'; 뭐 이런식으로 아무튼 명시적으로 클래스를 구분할 수 있는 방법을 만들기
custom Type Guard
if (isCar(machine))...
function isCar(arg: any): arg is Car {
return arg.type === 'CAR';
}
lodash같은거에서도 이런 방식이 많이 쓰인다.
3.9.7에서
strictPropertyInitialization을 켜면 어디서든 값이 지정이 되지 않으면 에러 발생
생성자든 어디든 초기화 해줘야됨
class Square4 {
area: number;
sideLength: number;
constructor(sideLength: number) {
this.sideLength = sideLength;
this.area = sideLength ** 2;
}
4.0.2 부터는 생성자에서 선언할 경우 타입 추론이 될 수도 있음
그러나 생성자 밖에서 다른 함수에서 될 경우 추론되지 않음
변수에 !
를 붙이면 assertion을 의미한다.
constructor와 처음에서 초기화 되지 않지만 어디에서 초기화 될거야라는 뜻